Skip to content

refactor(types): replace JsonDict with type-fest JsonObject and JsonValue#228

Merged
ryoppippi merged 5 commits intomainfrom
refactor/use-type-fest-json-types
Dec 15, 2025
Merged

refactor(types): replace JsonDict with type-fest JsonObject and JsonValue#228
ryoppippi merged 5 commits intomainfrom
refactor/use-type-fest-json-types

Conversation

@ryoppippi
Copy link
Copy Markdown
Contributor

@ryoppippi ryoppippi commented Dec 14, 2025

Summary

  • Replace custom JsonDict = Record<string, unknown> with type-fest's stricter JsonObject and JsonValue types
  • Add stringifyValue() helper for type-safe JSON value serialisation in URLs, headers, and form data
  • Update all source files, tests, and examples to use the new types

Motivation

The previous JsonDict type (Record<string, unknown>) was too permissive, allowing any value including non-JSON-serialisable types like undefined, Date, RegExp, and functions. By using type-fest's JsonObject and JsonValue, we get compile-time guarantees that values are actually JSON-serialisable.

Key Changes

Types (src/types.ts)

  • Import and re-export JsonObject and JsonValue from type-fest
  • Update JSONSchema interface to use JsonValue for enum, const, default, examples
  • Add explicit union type for index signature extensibility

Request Builder (src/requestBuilder.ts)

  • Add stringifyValue() helper that properly handles all JSON value types
  • Update dry run response to return null instead of undefined for empty body

Meta Tools (src/tool.ts)

  • Use JSON.parse(JSON.stringify(...)) to ensure search results are JSON-serialisable

Tests

  • Add type guard helpers for safe type narrowing
  • Update test expectations for stricter types
  • Remove tests for undefined values (not valid in JsonObject)

Test plan

  • All 166 tests pass
  • Lint passes with zero warnings/errors
  • Knip finds no unused exports

Summary by cubic

Replaced the custom JsonDict type with type-fest’s JsonObject and JsonValue for stricter, JSON-serializable types across the codebase. Added a stringifyValue helper for safe URL, header, and form serialization, and made dry-run responses fully JSON-safe.

  • Refactors

    • Switched all APIs, tools, request builder, examples, and tests from JsonDict to JsonObject/JsonValue.
    • Updated JSONSchema to use JsonValue for enum, const, default, and examples.
    • Added stringifyValue and used it for path, query, headers, and form serialization; null values are filtered from query; dry-run body is now null and headers are plain objects.
    • Ensured meta tools return JSON-serializable data and tightened types in feedback and headers handling.
  • Migration

    • Update tool execute signatures and params to JsonObject/JsonValue.
    • Stop using undefined in params/headers; use null where needed.
    • If you rely on dryRun, expect body: null and plain header objects.
    • Ensure parameters are valid JSON values; non-JSON types (e.g., Date, RegExp, functions) will be stringified or rejected at runtime.

Written for commit cd11a6d. Summary will update automatically on new commits.

…alue

Remove the custom `JsonDict = Record<string, unknown>` type alias in
favour of type-fest's stricter `JsonObject` and `JsonValue` types.

Key changes to src/types.ts:
- Import and re-export `JsonObject` and `JsonValue` from type-fest
- Update `JSONSchema` interface to use `JsonValue` instead of `unknown`
  for properties like `enum`, `const`, `default`, and `examples`
- Add explicit index signature union type for JSONSchema extensibility

This provides stronger type safety by ensuring values are actually
JSON-serialisable rather than accepting arbitrary `unknown` values.
Migrate all source files from the removed `JsonDict` type to the
type-fest `JsonObject` type. This commit updates method signatures
and internal type annotations across the codebase.

Files updated:
- src/tool.ts: Update execute method signatures and meta tool returns
- src/toolsets.ts: Update parameter and return types
- src/feedback.ts: Add explicit array types for results/errors,
  use JsonValue for parsed responses
- src/headers.ts: Update normaliseHeaders parameter type

Notable implementation changes:
- meta_search_tools now uses JSON.parse(JSON.stringify(...)) to ensure
  the return value is JSON-serialisable (removes undefined values from
  JSONSchema objects)
- Feedback tool now explicitly types its internal arrays to ensure
  type safety with the stricter JsonObject constraint
…ialisation

Add a dedicated `stringifyValue()` function to safely convert JsonValue
types to strings for use in URLs, headers, and form data. This replaces
direct `String()` calls which could produce `[object Object]` for
complex values.

The helper function:
- Returns strings as-is
- Converts numbers and booleans via String()
- Returns empty string for null values
- JSON-stringifies arrays and objects

Also updates the dry run response to properly serialise headers and body
to JSON-compatible values using `satisfies JsonObject` for type checking.
Update test files to work with the stricter JsonObject type:

src/tool.test.ts:
- Add isMetaToolSearchResults type guard function
- Add getSearchResults helper to safely extract search results
- Replace direct type assertions with type-safe helper calls

src/requestBuilder.test.ts:
- Update dry run test expectation: body is now `null` instead of
  `undefined` when no body params exist (null is JSON-serialisable)
- Add explicit type casts for runtime edge case tests that
  intentionally pass invalid types (Date, RegExp, circular refs)

src/headers.test.ts:
- Remove test for undefined values (not valid in JsonObject)
- Keep null value test (null is a valid JSON value)
Copilot AI review requested due to automatic review settings December 14, 2025 12:51
@ryoppippi ryoppippi requested a review from a team as a code owner December 14, 2025 12:51
Update example files to work with the new JsonObject type:

examples/meta-tools.ts:
- Import JsonObject from @stackone/ai
- Add explicit type annotation for intents array using
  `as const satisfies Array<{ intent: string; params: JsonObject }>`

examples/tanstack-ai-integration.test.ts:
- Simplify test structure and remove redundant assertions
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Dec 14, 2025

Open in StackBlitz

npm i https://pkg.pr.new/StackOneHQ/stackone-ai-node/@stackone/ai@228

commit: cd11a6d

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 12 files

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown
Contributor

@glebedel glebedel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ryoppippi ryoppippi merged commit 46fb73d into main Dec 15, 2025
13 checks passed
@ryoppippi ryoppippi deleted the refactor/use-type-fest-json-types branch December 15, 2025 12:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants